package game.entity.action;

import edu.monash.fit2099.engine.*;
import game.entity.actor.Brachiosaur;
import game.entity.actor.Stegosaur;
import game.entity.ground.Bush;
import game.entity.ground.Tree;
import game.entity.item.DeadBody;
import game.entity.item.Fruit;
import game.interfaces.Predator;
import game.interfaces.Vegetarian;
import game.util.LocationUtil;

import java.util.List;
import java.util.Random;

/**
 * Special Action for attacking other Actors.
 */
public class MoveToEatAction extends Action {

    /**
     * The Actor that is to be attacked
     */
    protected Actor target;
    /**
     * Random number generator
     */
    protected Random rand = new Random();

    /**
     * Constructor.
     *
     * @param target the Actor to attack
     */
    public MoveToEatAction(Actor target) {
        this.target = target;
    }

    @Override
    public String execute(Actor actor, GameMap map) {

        Location origin = map.locationOf(target);
        Location to = null;
        if (target instanceof Vegetarian) {
            if (target instanceof Stegosaur) {
//				只能吃灌木或掉在树下地上的水果
                to = findNearestVegetableFood(origin, map);
            }
            if (target instanceof Brachiosaur) {
//				只能吃树的果实
                to = findNearestTreeFood(origin, map);
            }
        } else if (target instanceof Predator) {
//			去找龙或尸体
            to = findNearestMeat(origin, map);
        }

        if (to != null) {
            Location nextStep = LocationUtil.calNextStep(origin, to);

            if (nextStep.canActorEnter(target)) {
                map.removeActor(target);
                nextStep.addActor(target);
            }

            String locationPrettyString = LocationUtil.getLocationPrettyString(origin);
            return locationPrettyString + target + " is moving to "
                    + LocationUtil.getLocationPrettyString(nextStep)
                    + " to eat, final dist is " + LocationUtil.getLocationPrettyString(to);
        }
        return "nothing to eat!";

    }

    /**
     * 找到最近的地上的水果或灌木
     *
     * @param origin
     * @param map
     * @return
     */
    private Location findNearestVegetableFood(Location origin, GameMap map) {
        NumberRange widths = map.getXRange();
        NumberRange heights = map.getYRange();
        int minDistance = Integer.MAX_VALUE;
        Location to = null;
        for (int x : widths) {
            for (int y : heights) {
                Location here = map.at(x, y);

//				检查灌木
                Ground ground = here.getGround();
                if (ground instanceof Bush) {
                    int distance = LocationUtil.distance(origin, here);
                    if (distance < minDistance) {
                        minDistance = distance;
                        to = here;
                    }
                } else {
//				不是灌木，则检查地上的水果，并保留最短距离
                    List<Item> items = here.getItems();
                    for (Item item : items) {
                        if (item instanceof Fruit) {
                            int distance = LocationUtil.distance(origin, here);
                            if (distance < minDistance) {
                                minDistance = distance;
                                to = here;
                            }
                        }
                    }
                }
            }
        }
        return to;
    }

    private Location findNearestTreeFood(Location origin, GameMap map) {
        NumberRange widths = map.getXRange();
        NumberRange heights = map.getYRange();
        int minDistance = Integer.MAX_VALUE;
        Location to = null;
        for (int x : widths) {
            for (int y : heights) {
                Location here = map.at(x, y);

//				检查树木
                Ground ground = here.getGround();
                int distance = LocationUtil.distance(origin, here);
                if (ground instanceof Tree) {
                    Tree tree = (Tree) ground;
                    boolean hasFruits = tree.hasFruits();
                    if (hasFruits && distance < minDistance) {
                        minDistance = distance;
                        to = here;
                    }
                }
            }
        }
        return to;
    }

    private Location findNearestMeat(Location origin, GameMap map) {
        NumberRange widths = map.getXRange();
        NumberRange heights = map.getYRange();
        int minDistance = Integer.MAX_VALUE;
        Location to = null;
        for (int x : widths) {
            for (int y : heights) {
                Location here = map.at(x, y);
                List<Item> items = here.getItems();
                Actor actor = here.getActor();
                int distance = LocationUtil.distance(origin, here);

                //食草龙
                if (actor instanceof Vegetarian) {
                    if (distance < minDistance) {
                        minDistance = distance;
                        to = here;
                    }
                }else{
                    //或者尸体
                    for (Item item : items) {
                        if(item instanceof DeadBody){
                            if (distance < minDistance) {
                                minDistance = distance;
                                to = here;
                            }
                        }
                    }
                }
            }
        }
        return to;
    }

    @Override
    public String menuDescription(Actor actor) {
        return actor + " attacks " + target;
    }


}
